export const jsonParse = function (value: string, defaultValue?: Record<string, unknown>) {
    if (typeof value !== 'string') {
        return defaultValue;
    }
    try {
        return JSON.parse(value);
    } catch (error) {
        console.error('Error parsing JSON:', error);
        return defaultValue;
    }
};
export const jsonStringify = function (
    value: unknown,
    replacer?: undefined | (number | string)[] | null
) {
    try {
        return JSON.stringify(value, replacer) || '';
    } catch (error) {
        console.error('Error stringify JSON:', error);
        return '';
    }
};

export const isAbsoluteURL = function (url: string) {
    return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
};
export const combineURLs = function (baseURL: string, relativeURL: string) {
    return relativeURL
        ? `${baseURL.replace(/\/?\/$/, '')}/${relativeURL.replace(/^\/+/, '')}`
        : baseURL;
};

export const buildFullPath = function (requestedURL: string, baseURL?: string) {
    if (baseURL && !isAbsoluteURL(requestedURL)) {
        return combineURLs(baseURL, requestedURL);
    }
    return requestedURL;
};

export const transformData = function (
    data: any,
    responseType: 'arraybuffer' | 'document' | 'json' | 'text' | 'stream'
) {
    if (typeof data === 'string' && responseType === 'json') {
        return jsonParse(data);
    }
    return data;
};
const isObject = (value: any): value is object => {
    return !!value && value.constructor === Object;
};
export const merge = <X extends Record<string | symbol | number, any>>(
    initial: X,
    override: X
): X => {
    if (!initial || !override) return initial ?? override ?? {};

    return Object.entries({ ...initial, ...override }).reduce((acc, [key, value]) => {
        return {
            ...acc,
            [key]: (() => {
                if (isObject(initial[key])) return merge(initial[key], value);
                return value;
            })()
        };
    }, {} as X);
};

export const objectToQueryString = (obj: Record<string, any>) => {
    const params = new URLSearchParams();
    for (const key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            params.append(key, obj[key]);
        }
    }
    return params.toString();
};

export const transformGetUrl = function (url: string, params: Record<string, any>) {
    // Check if the URL already has query parameters
    const hasQueryParams = url.includes('?');
    const queryString = objectToQueryString(params);

    // Handle URLs ending with '?'
    if (url.slice(-1) === '?') {
        return `${url}${queryString}`;
    }

    // If URL already has query parameters, append with &
    if (hasQueryParams && queryString) {
        return `${url}&${queryString}`;
    }

    // Default case: append ? and query parameters
    return queryString ? `${url}?${queryString}` : url;
};
export const hasProperty = <T, K extends keyof T>(
    obj: T,
    prop: K
): obj is T & Record<K, unknown> => {
    if (isObject(obj) && prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    }
    return false;
};
